package gu.sql2java;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Set;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;

import gu.sql2java.utils.DateSupport;

public class Sql2javaSupport {
	public static final Charset ISO_8559_1= Charset.forName("ISO-8859-1");
	private Sql2javaSupport() {
	}
	/**
	 * 返回buffer中所有字节(position~limit),不改变buffer状态
	 * @param buffer
	 * @return byte array
	 */
	public static final byte[] getBytesInBuffer(ByteBuffer buffer){
		int pos = buffer.position();
		try{
			byte[] bytes = new byte[buffer.remaining()];
			buffer.get(bytes);
			return bytes;
		}finally{
			buffer.position(pos);
		}
	}
	public static ByteBuffer toByteBuffer(String input){
		return input == null ? null : java.nio.ByteBuffer.wrap(input.getBytes(ISO_8559_1));
	}

	public static String toString(ByteBuffer newVal)
	{
		return newVal == null ? null : new String(getBytesInBuffer(newVal),ISO_8559_1);
	}
	/**
	 * get a date from a date string representation in one of the registered formats
	 * @param dateStr the date as string. 
	 * @param targetClass
	 * @return Date object ,otherwise null If (null or empty) or correct pattern was not found
	 * @deprecated replaced by {@link DateSupport#parseDateString(String, Class)}
	 */
	public static <D extends java.util.Date> D parseDateString(String dateStr, Class<D> targetClass)   {
		return DateSupport.parseDateString(dateStr,targetClass);
	}
	/**
	 * format {@link java.util.Date} to  string
	 * @param date
	 * @param format date time format string,use ISO8601 format if null
	 * @return ISO8601 date time format string or null if date is null
	 * @deprecated replaced by {@link DateSupport#formatDate(java.util.Date, String)}
	 */
	public static String formatDate(java.util.Date date, String format){
		return DateSupport.formatDate(date, format);
	}

	/**
	 * By calling {@link Class#isAssignableFrom (Class)} to search for subclasses of clazz in the iterator,
	 * return first or null If the input parameter is null or cannot be found
	 * @param iterable
	 * @param clazz
	 * @since 3.32.6
	 */
	public static <T> Class<? extends T> findSubClass(Iterable<Class<? extends T>> iterable, Class<?> clazz) {
		if (null != iterable && null != clazz) {
			return FluentIterable.from(iterable).filter(Predicates.subtypeOf(clazz)).first().orNull();
		}
		return null;
	}
	/**
	 * By calling {@link Class#isAssignableFrom (Class)} to search for class assignable from clazz in the iterator,
	 * return first or null If the input parameter is null or cannot be found
	 * @param iterable
	 * @param clazz
	 * @since 3.32.6
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <T> Class<? extends T> findSuperClass(Iterable<Class<? extends T>> iterable, final Class<?> clazz) {
		if (null != iterable && null != clazz) {
			if(iterable instanceof Set && ((Set)iterable).contains(clazz)) {
				return (Class<? extends T>) clazz;
			}
			return FluentIterable.from(iterable).filter(new Predicate<Class<?>>() {
				@Override
				public boolean apply(Class<?> input) {
					return input.isAssignableFrom(clazz);
				}
			}).first().orNull();
		}
		return null;
	}
	private static int indexOfFirstNull(Object...objects) {
		if(objects != null){
			for(int i=0;i< objects.length;++i){
				if(null == objects[i]){
					return i;
				}
			}
			return -1;
		}
		return -2;
	}
	/**
	 * @param objects 
	 * @return true if any one of object is null or objects is null 
	 * @since 3.32.6
	 */
	public static boolean hasNull(Object...objects) {
		return indexOfFirstNull(objects) != -1;
	}
	/**
	 * @param bean
	 * @return true if any primary key of B is null or B is null
	 * @since 3.32.6
	 */
	public static <T extends BaseBean >boolean hasNullPk(T bean){
		return (null == bean || hasNull(bean.primaryValues()));
	}
}
